local esc = minetest.formspec_escape

local function button_create(id, name, player_count, xp, pos, desc)
   local formspec =
      'formspec_version[3]'..
      'size[12,12]'..
      'field[0.5,1;5,.5;ID;ID Must not contain spaces or special characters;'..esc(id)..']'..
      'field[6,1;5,.5;name;Map Name;'..esc(name)..']'..
      'field[0.5,2;3,.5;player_count;Required # of Players;'..esc(player_count)..']'..
      'field[4,2;3,.5;xp;Required XP;'..esc(xp)..']'..
      'field[7.5,2;3,.5;pos;Spawn POS (x,y,z);'..esc(pos)..']'..
      'textarea[0.5,3;10,3;desc;Description of map;'..esc(desc)..']'..
      'button_exit[3,7;2,1;save;Submit]'
   return formspec
end

local function button_display(id, name, player_count, xp, pos, desc)
   local formspec =
      'formspec_version[3]'..
      'size[12,6]'..
      'textarea[0.5,1;5,2;;Map Name;'..esc(name)..']'..
      'textarea[0.5,2;5,2;;Required # of Players;'..esc(player_count)..']'..
      'textarea[0.5,3;5,2;;Required XP;'..esc(xp)..']'..
      'textarea[0.5,4;10,3;;Description of map;'..esc(desc)..']'
   return formspec
end

minetest.register_node('lobby:button_0', {
   description = 'Unconfigured Button',
   tiles = {'lobby_button_0.png'},
   groups = {breakable=1},
   light_source = 5,
   after_place_node = function(pos, placer)
      local meta = minetest.get_meta(pos)
      meta:set_string('owner', placer:get_player_name())
      meta:set_string('infotext', 'Unconfigured button')
      meta:set_string('id', '')
      meta:set_string('name', '')
      meta:set_string('player_count', '')
      meta:set_string('xp', '')
      meta:set_string('pos', '0,0,0')
      meta:set_string('desc', '')
   end,
   on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
      local player_name = clicker:get_player_name()
      local meta = minetest.get_meta(pos)
      local owner = meta:get_string('owner')
      local id = meta:get_string('id')
      local name = meta:get_string('name')
      local player_count = meta:get_string('player_count')
      local xp = meta:get_string('xp')
      local pos = meta:get_string('pos')
      local desc = meta:get_string('desc')
      meta:set_string('formspec', button_create(id, name, player_count, xp, pos, desc))
   end,
   on_receive_fields = function(pos, formname, fields, sender)
      local meta = minetest.get_meta(pos)
      local owner = meta:get_string('owner')
      if fields ['save'] then
         local player_name = sender:get_player_name()
         meta:set_string('infotext', fields.name)
         meta:set_string('id', fields.ID)
         meta:set_string('name', fields.name)
         meta:set_string('player_count', fields.player_count)
         meta:set_string('xp', fields.xp)
         meta:set_string('pos', fields.pos)
         meta:set_string('desc', fields.desc)
         local map_id = fields.ID
         local dist = tonumber(minetest.settings:get("map_generation_limit") or 31000)
         local x, y, z = string.match(fields.pos, "^(-?%d+),(-?%d+),(-?%d+)$")
         local pos_x = tonumber(x) or 50000
         local pos_y = tonumber(y) or 50000
         local pos_z = tonumber(z) or 50000
         local saveable = 0
         if pos_x > dist or pos_x < -dist or pos_y > dist or pos_y < -dist or pos_z > dist or pos_z < -dist then
            minetest.chat_send_player(player_name, 'Double check your spawn pos, values seem to be invalid.')
            saveable = 1
         end
         if lobby.savedata.IDs[map_id] then
            minetest.chat_send_player(player_name, 'That ID is already in use, you MUST change the ID.')
            saveable = 1
         end
         if saveable == 0 then
            local data = {}
            data.level_pos = {x = pos_x, y = pos_y+2, z = pos_z}
            data.xp = tonumber(fields.xp)
            lobby.savedata.IDs[map_id] = true
            lobby.savedata.data[map_id] = data
            minetest.swap_node(pos, {name = 'lobby:button_1'})
         end
      end
   end,
})

minetest.register_node('lobby:button_1', {
   description = 'Configured Button',
   tiles = {'lobby_button_1.png'},
   groups = {not_in_creative_inventory=1},
   drop = 'lobby:button_0',
   light_source = 14,
   on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
      local meta = minetest.get_meta(pos)
      local id = meta:get_string('id')
      local item = itemstack:get_name()
      if item ~= 'creative:tool_breaking' then
         local player_name = clicker:get_player_name()
         local owner = meta:get_string('owner')
         local name = meta:get_string('name')
         local player_count = meta:get_string('player_count')
         local xp = meta:get_string('xp')
         local pos = meta:get_string('pos')
         local desc = meta:get_string('desc')
         meta:set_string('formspec', button_display(id, name, player_count, xp, pos, desc))
      else
         minetest.swap_node(pos, {name = 'lobby:button_0'})
         lobby.savedata.IDs[id] = false
      end
   end,
   on_punch = function(pos, node, puncher, pointed_thing)
      local meta = minetest.get_meta(pos)
      local map_id = meta:get_string('id')
      if minetest.check_player_privs(puncher:get_player_name(), { creative = true }) then
         local game_data = lobby.savedata.data[map_id]
         local game_pos = game_data['level_pos']
         puncher:setpos({x=game_pos.x+(math.random(-2,2)),y=game_pos.y,z=game_pos.z+(math.random(-2,2))})
      else
         local needed_players = tonumber(meta:get_string('player_count'))
         local objs = minetest.get_objects_inside_radius(pos, 4)
         local player_count = 0
         local map_players = {}
         for _, obj in pairs(objs) do
            if obj:is_player() then
               player_count = player_count + 1
               local player_name = obj:get_player_name()
               table.insert(map_players, player_name)
            end
         end
         if player_count >= needed_players then
            if lobby.map[map_id] == 0 or lobby.map[map_id] == nil then
               minetest.chat_send_player(puncher:get_player_name(), 'you can start the game!')
               lobby.map[map_id] = player_count
               local traitor = math.random(1,player_count)
               lobby.xp[map_id] = 0
               lobby.votes[map_id] = 0
               lobby.corpses[map_id] = {}
               for i=1,player_count do
                  minetest.chat_send_player(map_players[i], 'Hold tight, loading the level.')
                  lobby.voted[map_players[i]] = true
                  if i == traitor then
                     minetest.chat_send_player(map_players[i], 'You\'re the imposter. Try to kill all the other players.')
                     minetest.chat_send_player(map_players[i], 'You\'ll get a weapon in a few seconds.')
                     lobby.traitors[map_id] = map_players[i]
                     local player = minetest.get_player_by_name(map_players[i])
                     local player_inv = player:get_inventory()
                     minetest.after(10, function()
                        player_inv:add_item('main', 'lobby:shank')
                     end)
                  end
                  local player = minetest.get_player_by_name(map_players[i])
                  local game_data = lobby.savedata.data[map_id]
                  local game_pos = game_data['level_pos']
                  local privs = {}
                  lobby.game[map_players[i]] = map_id
                  player:setpos({x=game_pos.x+(math.random(-2,2)),y=game_pos.y,z=game_pos.z+(math.random(-2,2))})
                  privs.interact = true
                  privs.shout = true
                  minetest.set_player_privs(map_players[i], privs)
               end
            else
               minetest.chat_send_player(puncher:get_player_name(), 'You can\'t join an in progress game.')
            end
         else
            minetest.chat_send_player(puncher:get_player_name(), 'Maybe not enough players? Right click the button for more information.')
         end
      end
   end,
})
